import mistune
from django.db import models
from django.contrib.auth.models import User
from django.template.loader import render_to_string
from django.utils.functional import cached_property


class Category(models.Model):
    STATUS_NORMAL = 1
    STATUS_DELETE = 0
    STATUS_CHOICES = (
        (STATUS_NORMAL, '正常'),
        (STATUS_DELETE, '删除'),
    )
    name = models.CharField(max_length=50, verbose_name="名称")
    status = models.PositiveIntegerField(default=STATUS_NORMAL,
                                         choices=STATUS_CHOICES,
                                         verbose_name="状态")
    is_nav = models.BooleanField(default=False, verbose_name="是否为导航")
    owner = models.ForeignKey(User,
                              verbose_name="所有者",
                              on_delete=models.CASCADE)
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

    class Meta:
        verbose_name = verbose_name_plural = "分类"

    def __str__(self):
        return self.name

    @classmethod
    def get_navs(cls):
        categories = cls.objects.filter(status=cls.STATUS_NORMAL)
        nav_categories = []
        normal_categories = []
        for cate in categories:
            if cate.is_nav:
                nav_categories.append(cate)
            else:
                normal_categories.append(cate)
        return {
            "navs": nav_categories,
            "categories": normal_categories,
        }


class Tag(models.Model):
    STATUS_NORMAL = 1
    STATUS_DELETE = 0
    STATUS_CHOICES = (
        (STATUS_NORMAL, '正常'),
        (STATUS_DELETE, '删除'),
    )
    name = models.CharField(max_length=10, verbose_name="名称")
    status = models.PositiveIntegerField(default=STATUS_NORMAL,
                                         choices=STATUS_CHOICES,
                                         verbose_name="状态")
    owner = models.ForeignKey(User,
                              verbose_name="所有者",
                              on_delete=models.CASCADE)
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

    class Meta:
        verbose_name = verbose_name_plural = "标签"

    def __str__(self):
        return self.name


class Post(models.Model):
    """
    文章表
    """
    STATUS_NORMAL = 1
    STATUS_DELETE = 0
    STATUS_DRAFT = 2
    STATUS_CHOICES = (
        (STATUS_NORMAL, '正常'),
        (STATUS_DELETE, '删除'),
        (STATUS_DRAFT, '草稿'),
    )
    title = models.CharField(max_length=250, verbose_name="标题")
    desc = models.CharField(max_length=250, verbose_name="摘要")
    content = models.TextField(verbose_name="正文")
    content_html = models.TextField(verbose_name="正文 html 代码",
                                    blank=True,
                                    editable=False)
    author = models.ForeignKey(User,
                               on_delete=models.CASCADE,
                               verbose_name="作者")
    status = models.PositiveIntegerField(default=STATUS_NORMAL,
                                         choices=STATUS_CHOICES,
                                         verbose_name="状态")
    category = models.ForeignKey(Category,
                                 null=True,
                                 blank=True,
                                 on_delete=models.SET_NULL,
                                 verbose_name="分类")
    tag = models.ManyToManyField(Tag, null=True, blank=True, verbose_name="标签")
    created_time = models.DateTimeField(auto_now_add=True)
    updated_time = models.DateTimeField(auto_now=True)
    pv = models.PositiveIntegerField(default=1)
    uv = models.PositiveIntegerField(default=1)

    class Meta:
        ordering = ('-updated_time', )
        verbose_name = verbose_name_plural = "文章"

    def __str__(self):
        return self.title

    @staticmethod
    def get_by_tag(tag_id):
        try:
            tag = Tag.objects.get(id=tag_id)
        except Tag.DoesNotExist:
            tag = None
            post_list = []
        else:
            post_list = tag.post_set.filter(
                status=Post.STATUS_NORMAL).select_related(
                    "author", 'category')
        return post_list, tag

    @staticmethod
    def get_by_category(category_id):
        try:
            category = Category.objects.get(id=category_id)
        except Category.DoseNotExist:
            category = None
            post_list = []
        else:
            post_list = category.post_set.filter(
                status=Post.STATUS_NORMAL).select_related(
                    "author", 'category')
        return post_list, category

    @classmethod
    def latest_post(cls):
        return cls.objects.filter(status=cls.STATUS_NORMAL)

    @classmethod
    def hot_posts(cls):
        return cls.objects.filter(status=cls.STATUS_NORMAL).order_by('-pv')

    def save(self, *args, **kwargs):
        self.content_html = mistune.markdown(self.content)
        super().save(*args, **kwargs)

    @cached_property
    def tags(self):
        return ','.join(self.tag.values_list('name', flat=True))


class SideBar(models.Model):
    DISPLAY_HTML = 1
    DISPLAY_LATEST = 2
    DISPLAY_HOT = 3
    DISPLAY_COMMENT = 4
    STATUS_SHOW = 1
    STATUS_HIDE = 0
    STATUS_ITEM = (
        (STATUS_SHOW, "展示"),
        (STATUS_HIDE, "隐藏"),
    )
    SIDE_TYPE = (
        (DISPLAY_HTML, "HTML"),
        (DISPLAY_LATEST, "最新的文章"),
        (DISPLAY_HOT, "最热的文章"),
        (DISPLAY_COMMENT, "最近的评论"),
    )
    title = models.CharField(max_length=50, verbose_name="标题")
    display_type = models.PositiveIntegerField(default=1,
                                               choices=SIDE_TYPE,
                                               verbose_name="展示类型")
    content = models.CharField(max_length=500,
                               blank=True,
                               verbose_name="内容",
                               help_text="如果设置的不是 HTML 类型，可为空")
    status = models.PositiveIntegerField(default=STATUS_SHOW,
                                         choices=STATUS_ITEM,
                                         verbose_name="状态")
    owner = models.ForeignKey(User,
                              on_delete=models.CASCADE,
                              verbose_name="作者")
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

    class Meta:
        verbose_name = verbose_name_plural = "侧边栏"

    @classmethod
    def get_all(cls):
        return cls.objects.filter(status=cls.STATUS_SHOW)

    @property
    def content_html(self):
        """
        直接渲染模板
        """
        from comment.models import Comment
        result = None
        if self.display_type == self.DISPLAY_HTML:
            result = self.content
        elif self.display_type == self.DISPLAY_LATEST:
            context = {"posts": Post.latest_post()}
            result = render_to_string('blog/sidebar_posts.html', context)
        elif self.display_type == self.DISPLAY_HOT:
            context = {"posts": Post.hot_posts()}
            result = render_to_string('blog/sidebar_posts.html', context)
        elif self.display_type == self.DISPLAY_COMMENT:
            context = {
                "comments":
                Comment.objects.filter(status=Comment.STATUS_NORMAL)
            }
            result = render_to_string('blog/sidebar_comments.html', context)
        return result


class Link(models.Model):
    STATUS_NORMAL = 1
    STATUS_DELETE = 0
    STATUS_ITEMS = (
        (STATUS_NORMAL, "正常"),
        (STATUS_DELETE, "删除"),
    )
    title = models.CharField(max_length=50, verbose_name="标题")
    href = models.URLField(verbose_name="链接")
    status = models.PositiveIntegerField(default=STATUS_NORMAL,
                                         choices=STATUS_ITEMS,
                                         verbose_name="状态")
    weight = models.PositiveIntegerField(default=1,
                                         choices=zip(range(1, 6), range(1, 6)),
                                         verbose_name="权重",
                                         help_text="权重高展示顺序靠前")
    owner = models.ForeignKey(User,
                              verbose_name="作者",
                              on_delete=models.CASCADE)
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

    class Meta:
        verbose_name = verbose_name_plural = "友情链接"

    def __str__(self):
        return self.title
